package common.util;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 多次读写BODY用HTTP REQUEST - 解决流只能读一次问题
 *
 * @author 米泽鹏
 * @since 2021-07-31 5:12 下午
 */
@Slf4j
public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {

	private final byte[] body;

	public MultiReadHttpServletRequest(HttpServletRequest request) {
		super(request);
		body = getBodyString(request).getBytes(StandardCharsets.UTF_8);
	}

	@Override
	public BufferedReader getReader() {
		return new BufferedReader(new InputStreamReader(getInputStream()));
	}

	@Override
	public ServletInputStream getInputStream() {

		final ByteArrayInputStream bais = new ByteArrayInputStream(body);

		return new ServletInputStream() {

			@Override
			public int read() {
				return bais.read();
			}

			@Override
			public boolean isFinished() {
				return false;
			}

			@Override
			public boolean isReady() {
				return false;
			}

			@Override
			public void setReadListener(ReadListener readListener) {

			}
		};
	}

	/**
	 * 获取请求Body
	 */
	private String getBodyString(ServletRequest request) {
		StringBuilder sb = new StringBuilder();
		try (InputStream inputStream = request.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
			String line;
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
		} catch (IOException e) {
			log.error("获取请求Body失败", e);
		}
		return sb.toString();
	}

	/**
	 * 将前端请求的表单数据转换成json字符串 - 前后端一体的情况下使用
	 */
	public String getBodyJsonStrByForm(ServletRequest request) {
		Map<String, Object> bodyMap = new HashMap<>(16);
		try {
			// 参数定义
			String paraName;
			// 获取请求参数并转换
			Enumeration<String> e = request.getParameterNames();
			while (e.hasMoreElements()) {
				paraName = e.nextElement();
				bodyMap.put(paraName, request.getParameter(paraName));
			}
		} catch (Exception e) {
			log.error("请求参数转换错误", e);
		}
		return JSONObject.toJSONString(bodyMap);
	}

	/**
	 * 将前端传递的json数据转换成json字符串 - 前后端分离的情况下使用
	 */
	public String getBodyJsonStrByJson(HttpServletRequest request) {

		StringBuilder json = new StringBuilder();
		String line;
		try {
			BufferedReader reader = request.getReader();
			while ((line = reader.readLine()) != null) {
				json.append(line);
			}
		} catch (Exception e) {
			log.error("请求参数转换错误", e);
		}
		return json.toString();
	}

	/**
	 * 解决swagger分页查询时的报错：Content-length different from byte array length
	 * 重写getContentLength()和getContentLengthLong()
	 */
	@Override
	public int getContentLength() {
		return body.length;
	}

	@Override
	public long getContentLengthLong() {
		return body.length;
	}

}
